package com.example.myapplication.camera1.camrea;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import android.app.Application;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;

import com.example.myapplication.camera1.view.MaskSurfaceView;
import com.media.photocamera.utils.CameraFileUtils;

import top.zibin.luban.Luban;

public class CameraHelper {
    private final String TAG = "CameraHelper";
    private ToneGenerator tone;
    private String filePath;
    private boolean isPreviewing;

    private static CameraHelper helper;
    private Camera camera;
    private MaskSurfaceView surfaceView;

    //	照片质量
    private int picQuality = 60;

    private int limit = 1024;

    public void setLimit(int limit) {
        this.limit = limit;
    }

    //	照片尺寸
    private Size previewSize;

    //	闪光灯模式(default：自动、ANTIBANDING_OFF：关闭)
    private String flashlightStatus = Parameters.ANTIBANDING_OFF;
    private Size pictureSize;

    public String getFlashlightStatus() {
        return flashlightStatus;
    }

    private SurfaceHolder holder;
    private int format;
    private int width;
    private int height;
    private int screenHeight;
    private int screenWidth;
    private double screenProp;

    public enum Flashlight {
        AUTO, ON, OFF
    }

    private CameraHelper() {
    }

    public static synchronized CameraHelper getInstance() {
        if (helper == null) {
            helper = new CameraHelper();
        }
        return helper;
    }

    /**
     * 设置照片质量
     *
     * @param picQuality
     * @return
     */
    public CameraHelper setPicQuality(int picQuality) {
        this.picQuality = picQuality;
        return helper;
    }

    public Camera getCamera() {
        return camera;
    }

    /**
     * 设置闪光灯模式
     *
     * @param status
     * @return
     */
    public CameraHelper setFlashlight(Flashlight status) {
        try {
            switch (status) {
                case AUTO:
                    this.flashlightStatus = Parameters.FLASH_MODE_AUTO;
                    break;
                case ON:
                    this.flashlightStatus = Parameters.FLASH_MODE_ON;
                    break;
                case OFF:
                    this.flashlightStatus = Parameters.FLASH_MODE_OFF;
                    break;
                default:
                    this.flashlightStatus = Parameters.FLASH_MODE_AUTO;
            }
            setFlashMode(this.flashlightStatus);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return helper;
    }

    public void setFlashMode(String flashlightStatus) {
        this.flashlightStatus = flashlightStatus;
        if (isFrontCameara()) {
            //如果前置不能设置
            return;
        }
        if (camera != null) {
            //设置闪光灯
            Parameters parameters = camera.getParameters();
            parameters.setFlashMode(this.flashlightStatus);
            camera.setParameters(parameters);
        }
    }

    /**
     * 设置文件保存路径(default: /mnt/sdcard/DICM)
     *
     * @param path
     * @return
     */
    public CameraHelper setPictureSaveDictionaryPath(String path) {
        this.filePath = path;
        return helper;
    }

    public CameraHelper setMaskSurfaceView(MaskSurfaceView surfaceView) {
        this.surfaceView = surfaceView;
        return helper;
    }

    /**
     * 打开相机并开启预览
     *
     * @param holder       SurfaceHolder
     * @param format       图片格式
     * @param width        SurfaceView宽度
     * @param height       SurfaceView高度
     * @param screenWidth  屏幕宽度
     * @param screenHeight 屏幕高度
     */
    public void openCamera(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) {
        if (this.camera != null) {
            this.camera.release();
        }
        Log.e(TAG, "height:" + height + ",width:" + width + ",screenHeight:" + screenHeight + ",screenWidth:" + screenWidth);
        this.holder = holder;
        this.format = format;
        this.width = width;
        this.height = height;
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.screenProp = (double) height / (double) width;
        this.camera = Camera.open(this.cameraPosition % Camera.getNumberOfCameras());
        this.initParameters(holder, format, width, height, screenWidth, screenHeight);
        this.startPreview();
    }

    public int cameraPosition = 0;//1代表前置摄像头,0代表后置摄像头,默认打开前置摄像头

    public void setFrontCamera(boolean isFront) {
        if (isFront) {
            cameraPosition = 1;
        } else {
            cameraPosition = 0;
        }
    }

    public boolean isFrontCameara() {
        if (cameraPosition == 1) {
            //前置摄像头
            return true;
        } else {
            //后置摄像头
            return false;
        }
    }

    public int changeCamera() {
        if (this.camera != null) {
            this.camera.cancelAutoFocus();
            this.camera.setPreviewCallback(null);
            this.camera.stopPreview();
            this.camera.release();
            this.camera = null;
        }
        cameraPosition = (cameraPosition + 1) % Camera.getNumberOfCameras();
        openCamera(this.holder, this.format, this.width, this.height, this.screenWidth, this.screenHeight);
        return cameraPosition;
    }

    /**
     * 照相
     */
    public void tackPicture(Application application, final OnCaptureCallback callback) {
        this.camera.autoFocus(null);
        camera.takePicture(new ShutterCallback() {
            @Override
            public void onShutter() {
                if (tone == null) {
                    //发出提示用户的声音
                    tone = new ToneGenerator(AudioManager.STREAM_MUSIC, ToneGenerator.MAX_VOLUME);
                }
                tone.startTone(ToneGenerator.TONE_PROP_BEEP);
            }
        }, null, new PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            String filepath = savePicture(data);
                            boolean success = false;
                            if (filepath != null) {
                                success = true;
                            }
                            File file = new File(filepath);
                            Log.d(TAG, "文件压缩前：" + " 大小：" + file.length() + "   " + CameraFileUtils.getReadableFileSize(file.length()) + " 路径：" + file.getAbsolutePath());
                            if (file.length() > limit * 1024) {
                                long startZipTime = System.currentTimeMillis();
                                File file1 = Luban.with(application).get(file.getAbsolutePath());
                                long endZipTime = System.currentTimeMillis();
                                Log.d(TAG, "文件压缩后：" + " 大小：" + CameraFileUtils.getReadableFileSize(file1.length()) + " 用时：" + (endZipTime - startZipTime) + " 路径：" + file1.getAbsolutePath());
                                filepath = file1.getAbsolutePath();
                            }
                            stopPreview();
                            callback.onCapture(success, filepath);
                        } catch (Exception e) {
                            e.printStackTrace();
                            callback.onCapture(false, null);
                        }
                    }
                }).start();

            }
        });
    }

    /**
     * 裁剪并保存照片
     *
     * @param data
     * @return
     */
    private String savePicture(byte[] data) {
        File imgFileDir = getImageDir();
        if (!imgFileDir.exists() && !imgFileDir.mkdirs()) {
            return null;
        }
        //文件路径路径
        String imgFilePath = imgFileDir.getPath() + File.separator + this.generateFileName();
        Bitmap b = this.cutImage(data);
        File imgFile = new File(imgFilePath);
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            fos = new FileOutputStream(imgFile);
            bos = new BufferedOutputStream(fos);
            b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (Exception error) {
            error.printStackTrace();
            return null;
        } finally {
            try {
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
                if (bos != null) {
                    bos.flush();
                    bos.close();
                }
            } catch (IOException e) {
            }
        }
        return imgFilePath;
    }

    /**
     * 生成图片名称
     *
     * @return
     */
    private String generateFileName() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss", Locale.getDefault());
        String strDate = dateFormat.format(new Date());
        return "img_" + strDate + ".jpg";
    }

    /**
     * @return
     */
    private File getImageDir() {
        String path = null;
        if (this.filePath == null || this.filePath.equals("")) {
            path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath();
        } else {
            path = filePath;
        }
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }
        return file;
    }

    /**
     * 初始化相机参数
     *
     * @param holder       SurfaceHolder
     * @param format       图片格式
     * @param width        SurfaceView宽度
     * @param height       SurfaceView高度
     * @param screenWidth  屏幕宽度
     * @param screenHeight 屏幕高度
     */
    private void initParameters(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) {
        try {
            Parameters mParams = this.camera.getParameters();

            if (width > height) {
                //横屏
                this.camera.setDisplayOrientation(0);
            } else {
                //竖屏
                this.camera.setDisplayOrientation(90);
            }

            //照片质量
            mParams.set("jpeg-quality", picQuality);

            //设置照片格式
            mParams.setPictureFormat(PixelFormat.JPEG);

            //设置闪光灯
//            mParams.setFlashMode(this.flashlightStatus);
            previewSize = CameraParamUtil.getInstance().getPreviewSize(mParams
                    .getSupportedPreviewSizes(), 1200, (float) screenProp);
            pictureSize = CameraParamUtil.getInstance().getPictureSize(mParams
                    .getSupportedPictureSizes(), 1200, (float) screenProp);
            Log.e(TAG, "previewSize:w " + previewSize.width + " × h " + previewSize.height);
            mParams.setPreviewSize(previewSize.width, previewSize.height);
            Log.e(TAG, "pictureSize:w " + pictureSize.width + " × h" + pictureSize.height);
            mParams.setPictureSize(pictureSize.width, pictureSize.height);
            List<String> focusModes = mParams.getSupportedFocusModes();
            if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            }
//            if (!isFrontCameara()) {
//                mParams.setFocusMode(Parameters.FOCUS_MODE_AUTO);
//            }
            camera.setParameters(mParams);
            camera.setPreviewDisplay(holder);
            camera.startPreview();
        } catch (Exception e) {
            Log.e(TAG, "相机参数设置错误");
        }
    }

    /**
     * 释放Camera
     */
    public void releaseCamera() {
        if (this.camera != null) {
            if (this.isPreviewing) {
                this.stopPreview();
            }
            this.camera.setPreviewCallback(null);
            isPreviewing = false;
            this.camera.release();
            this.camera = null;
        }
    }

    /**
     * 停止预览
     */
    private void stopPreview() {
        if (this.camera != null && this.isPreviewing) {
            this.camera.stopPreview();
            this.isPreviewing = false;
        }
    }

    /**
     * 开始预览
     */
    public void startPreview() {
        if (this.camera != null) {
            this.camera.startPreview();
            this.camera.autoFocus(null);
            this.isPreviewing = true;
        }
    }

    /**
     * 自动对焦
     */

    public void autoFocus(Camera.AutoFocusCallback cb) {
        if (this.isPreviewing && this.camera != null) {
            this.camera.autoFocus(cb);
        }
       /* if (this.camera == null) {
            return;
        }
        Parameters parameters = this.camera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//连续对焦
        this.camera.setParameters(parameters);
        this.camera.cancelAutoFocus();*/
    }


    /**
     * 裁剪照片
     *
     * @param data
     * @return
     */
    private Bitmap cutImage(byte[] data) {
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        if (this.surfaceView.getWidth() < this.surfaceView.getHeight()) {
            //竖屏旋转照片
            Matrix matrix = new Matrix();
            matrix.reset();
            cameraPosition = cameraPosition % Camera.getNumberOfCameras();
            switch (cameraPosition) {
                case 0:
                    matrix.preRotate(90);
                    break;
                case 1://前
                    matrix.postScale(-1, 1);
                    matrix.preRotate(270);
                    break;
            }
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        if (this.surfaceView == null) {
            return bitmap;
        } else {
           /* int[] sizes = this.surfaceView.getMaskSize();
            if (sizes[0] == 0 || sizes[1] == 0) {
                return bitmap;
            }

            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            int x = (w - sizes[0]) / 2;
            int y = (h - sizes[1]) / 2;

            return Bitmap.createBitmap(bitmap, x, y, sizes[0], sizes[1]);*/

            int[] sizes = this.surfaceView.getMaskSize();
            if (sizes[0] == 0 || sizes[1] == 0) {
                return bitmap;
            }

//            (double)height/(double)width;
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            int targetx = (int) (w * sizes[0] / (double) this.width);
            int targety = (int) (h * sizes[1] / (double) this.height);
            int x = (w - targetx) / 2;
            int y = (h - targety) / 2;

            return Bitmap.createBitmap(bitmap, x, y, targetx, targety);
        }
    }
}
